package com.demo.redpacket.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.demo.redpacket.model.RedPacket;
import com.google.common.primitives.Doubles;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;

// 定义红包的控制器
@RestController
@Slf4j
public class RedPacketController {

    public static final String RED_PACKET_RAIN_KEY = "redpacket:rain:";
    public static final String RED_PACKET_CONSUMER_KEY = "redpacket:consumer:";
    public static final String RED_PACKET_RECORD_KEY = "redpacket:record:";

    @Autowired
    private RedisTemplate redisTemplate;

    // 定义发红包的方法
    @RequestMapping("/send")
    public String sendRedPacket(int totalMoney, int totalPeopleNum) {
        // 拆红包, 生成红包列表
        List<RedPacket> redPacketList = this.divideRedPacket(totalMoney, totalPeopleNum);
        // 发红包, 并且把红包列表放入redis
        String redPacketRainId = IdUtil.objectId();
        String key = RED_PACKET_RAIN_KEY + redPacketRainId;
        redisTemplate.opsForList().leftPushAll(key, redPacketList);
        // 设置红包过期时间
        redisTemplate.expire(key, 1, TimeUnit.DAYS);
        // 发红包结束, 返回前台
        return "红包雨活动id："+redPacketRainId + "，红包列表：" + JSONUtil.toJsonStr(redPacketList);
    }


    @RequestMapping("/receiveByLua")
    public String receiveRedPacketByLua(String key, String userId) {
        try {
            String redPacketConsumerKey = RED_PACKET_CONSUMER_KEY + key;
            String redPacketRainKey  = RED_PACKET_RAIN_KEY + key;
            String redPacketRecordKey =  RED_PACKET_RECORD_KEY + key;
            //调用lua脚本并执行
            DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();
            redisScript.setResultType(String.class);
            redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("redpacket.lua")));
            //lua文件存放在resources目录下的redis文件夹内
            LinkedHashMap result = (LinkedHashMap) redisTemplate.execute(redisScript, Arrays.asList(redPacketConsumerKey,redPacketRainKey,redPacketRecordKey,userId));
            log.info("Receive Red Packet: " + key + ", " + JSONUtil.toJsonStr(result));
            return "Receive Red Packet: " + key + ", " + JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 拆红包的算法,二倍均值法, 保证每个人都有红包, 返回值为List<Double>
    public List<RedPacket> divideRedPacket(double totalAmount, int totalPeopleNum) {
        List<RedPacket> redPacketList = new ArrayList<>();
        //总金额
        double restAmount = totalAmount;
        //总人数
        int restPeopleNum = totalPeopleNum;
        Random random = new Random();
        RedPacket redPacket = null;
        for (int i = 0; i < totalPeopleNum - 1; i++) {
            // 随机范围：[0.01,剩余人均金额的两倍)，左闭右开
            double amount = random.nextDouble() * 2 * restAmount / restPeopleNum;
            amount = Math.max(0.01, amount);
            restAmount -= amount;
            restPeopleNum--;
            // amount 保留两位小数
            amount = Doubles.tryParse(String.format("%.2f", amount));
            redPacket = new RedPacket(IdWorker.getIdStr(),amount);
            redPacketList.add(redPacket);
        }
        // 最后一个红包的数据保留两位小数
        restAmount = Doubles.tryParse(String.format("%.2f", restAmount));
        redPacket = new RedPacket(IdWorker.getIdStr(),restAmount);
        redPacketList.add(redPacket);
        return redPacketList;
    }

}
